package cn.topcodes.tcsf.admin.web.filterrequest;

import cn.topcode.unicorn.utils.CollectionUtil;
import cn.topcode.unicorn.utils.IpUtil;
import cn.topcode.unicorn.utils.SpringContextHolder;
import cn.topcodes.tcsf.admin.domain.entity.SysAccessLog;
import cn.topcodes.tcsf.admin.service.log.AccessLogService;
import cn.topcodes.tcsf.admin.service.SystemPropertyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

/**
 * 请求拦截器
 * 拦截用于请求响应内容日志
 * @author  Unicorn
 */
public class RequestFilter implements Filter {

    private Logger logger = LoggerFactory.getLogger(RequestFilter.class);

//    @Autowired
//    private AccessLogService accessLogService;
//
//    @Autowired
//    private SystemPropertyService propService;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        AccessLogService accessLogService = SpringContextHolder.getBean(AccessLogService.class);
        SystemPropertyService propService = SpringContextHolder.getBean(SystemPropertyService.class);

        if(propService != null && accessLogService != null && propService.isAccessLogOn()) {
            Date requestTime = new Date();

            HttpServletRequest request = (HttpServletRequest) servletRequest;
            HttpServletResponse response = (HttpServletResponse) servletResponse;

            // 防止流读取一次后就没有了, 所以需要将流继续写出去
            ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(request);
            String requestBody = HttpHelper.getBodyString(requestWrapper);

            filterChain.doFilter(requestWrapper, servletResponse);

            //  保存记录
            SysAccessLog accessLog = new SysAccessLog();
            accessLog.setUrl(request.getRequestURI());
            accessLog.setMethod(request.getMethod());
            accessLog.setIp(IpUtil.getIp(request));

            //	处理请求后记录响应时间及耗费毫秒数
            Date responseTime = new Date();
            int consuming = (int) (responseTime.getTime() - requestTime.getTime());
            accessLog.setRequestTime(requestTime);
            accessLog.setResponseTime(responseTime);
            accessLog.setConsuming(consuming);

            //  记录请求和响应头部
            String requestHeader = handleRequestHeader(request);
            accessLog.setRequestHead(requestHeader);

            String responseHeader = handleResponseHeader(response);
            accessLog.setResponseHead(responseHeader);

			accessLog.setRequestBody(requestBody);
//			response.get
//			accessLog.setResponseBody();*/
//            response.getOutputStream()
//            HttpServletResponseWrapper

            accessLogService.create(accessLog);
            return;
        }

        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {

    }

    /*将请求头部转换为键值对形式的字符串*/
    private String handleRequestHeader(HttpServletRequest request) {
        List<String> headers = new ArrayList<String>();
        Enumeration<String> requestHeader = request.getHeaderNames();
        while(requestHeader.hasMoreElements()) {
            String header = requestHeader.nextElement();
            String value = request.getHeader(header);
            headers.add(header + ":" + value);
        }
        String headerStr = CollectionUtil.array2String(headers);
        return headerStr;
    }

    /*将响应头部转换为键值对形式的字符串*/
    private String handleResponseHeader(HttpServletResponse response) {
        List<String> headers = new ArrayList<String>();
        Collection<String> responseHeader = response.getHeaderNames();
        for(String header : responseHeader) {
            String value = response.getHeader(header);
            headers.add(header + ":" + value);
        }
        String headerStr = CollectionUtil.array2String(headers);
        return headerStr;
    }
}
